#ifndef RG_QUAD_H
#define RG_QUAD_H

#include "vector.h"
#include "transform.h"
#include "config.h"

namespace rg{

  struct ray{
    vec3 o,d;
    real t;

    ray(const vec3& ori,const vec3& dir,const real& s=inf):o(ori),d(dir),t(s){}
    vec3 end()const {return o+d*t;}
  };

  struct quad{
    vec3 ori;
    vec3 u,v;
    
    explicit quad(const vec3& o=vec3(),const vec3& x=vec3(),const vec3& y=vec3()):
      ori(o),u(x),v(y){}

    bool intersect(ray& r)const{
      vec3 p0=ori,p1=ori+u,p2=p1+v,p3=ori+v;
      bool hit=false;

      mat3x3 m(-r.d,p1-p0,p2-p0);
      vec3 b(r.o - p0);
      mat3x3 inv=inverse(m);
      vec3 x=inv * b;

      real t=x[0],k=x[1],j=x[2];
      if(t>0 && t<r.t &&
	 k>=0 && k<=1 &&
	 j>=0 && j<=1 &&
	 k+j<=1){
	r.t=t;
	return true;
      }

      m=mat3x3(-r.d,p2-p0,p3-p0);
      b=vec3(r.o - p0);
      inv=inverse(m);
      x=inv * b;

      t=x[0],k=x[1],j=x[2];
      if(t>0 && t<r.t &&
	 k>=0 && k<=1 &&
	 j>=0 && j<=1 &&
	 k+j<=1){
	r.t=t;
	return true;
      }
      return false;
    }

    vec3 patch2pos(int i)const{
      int x=i % subdiv_level;
      int y=i / subdiv_level;
      real xunit = u.len() / subdiv_level;
      real yunit = v.len() / subdiv_level;
      return ori + u.norm() * xunit * x + v.norm() * yunit * y;
    }
    int pos2patch(const vec3& p)const{
      vec3 d=p-ori;
      real proj_x=dot(u.norm(), d);
      real proj_y=dot(v.norm(), d);
      real xunit = u.len() / subdiv_level;
      real yunit = v.len() / subdiv_level;
      real x=proj_x / xunit;
      real y=proj_y / yunit;
      int i = int(y) * subdiv_level + int(x);
      return i;
    }
    real area()const{return cross(u,v).len();}
  };

}//namesapce rg

#endif
